import { Rect } from 'cc';
import { Director } from 'cc';
import { director } from 'cc';
import { UITransform } from 'cc';
import { Node, UIRenderer, _decorator } from 'cc';
const { ccclass, property } = _decorator;

const IS_OPEN_BATCH = true;//是否打开渲染合批

function emptyRender(){}

@ccclass('BatchRepateItems')
export class BatchRepateItems extends UIRenderer {
    private orderRenders:any[]; //需要渲染的对象集合
    private needUpdate:boolean = true; //是否需要更新
    private isClearSlef:boolean = false; //是否清理了自己
    
    onLoad(): void {
        director.on(Director.EVENT_BEFORE_DRAW, this.initBatchRenders, this);
        // this.initBatchRenders();
    }

    /**需要清理自己 */
    private clearSlef(){
        this.isClearSlef = true;
        if(this.orderRenders){
            this.clearAllNodeOn(this.node);
            this.orderRenders = null;
        }
    }

    /**清理所有节点和子节点的事件监听 */
    private clearAllNodeOn(node:Node){
        node.off(Node.EventType.CHILD_ADDED, this.onNeedUpdateRendersFromAdd, this);
        node.off(Node.EventType.CHILD_REMOVED, this.onNeedUpdateRendersFromRemove, this);
        
        for (const cn of node.children) {
            this.clearAllNodeOn(cn);
        }
    }

    /**需要更新节点 */
    private onNeedUpdateRendersFromAdd(node:Node){
        if(!this.isClearSlef && node){
            const renders = node.getComponentsInChildren(UIRenderer);
            if(renders && renders.length > 0){
                this.needUpdate = true;
            }
        }
    }

    /**需要更新节点 */
    private onNeedUpdateRendersFromRemove(node:Node){
        if(!this.isClearSlef && node){
            const renders:any[] = node.getComponentsInChildren(UIRenderer);
            if(renders && renders.length > 0){
                this.needUpdate = true;
            }

            //子节点被移除时要还原_render函数保证其在别的地方能正确渲染
            for (const r of renders) {
                if(r._realRenderFunc){
                    r._render = r._realRenderFunc;
                    r._realRenderFunc = null;
                }
            }

            this.clearAllNodeOn(node);
        }
    }
    
    /**设置节点的顺序 */
    private setNodeOrder(node:any, orderAny:any){
        node.____order = orderAny.order++;
        node.on(Node.EventType.CHILD_ADDED, this.onNeedUpdateRendersFromAdd, this);
        node.on(Node.EventType.CHILD_REMOVED, this.onNeedUpdateRendersFromRemove, this);

        for (const cn of node.children) {
            this.setNodeOrder(cn, orderAny);
        }
    }
    
    private initBatchRenders(){
        if(IS_OPEN_BATCH && !this.isClearSlef && this.needUpdate){
            this.needUpdate = false;

            //处理子节点下的 BatchItems
            const subBatchItems = this.node.getComponentsInChildren(BatchRepateItems);
            if(this == subBatchItems[0]){
                subBatchItems.splice(0, 1);
            }

            for (const sbi of subBatchItems) {
                if(sbi.enabled){
                    sbi.clearSlef();
                }
            }

            this.node.on(Node.EventType.CHILD_ADDED, this.onNeedUpdateRendersFromAdd, this);
            this.node.on(Node.EventType.CHILD_REMOVED, this.onNeedUpdateRendersFromRemove, this);
            for (const cn of this.node.children) {
                this.setNodeOrder(cn, {order:0});
            }

            this.orderRenders = this.node.getComponentsInChildren(UIRenderer);
            if(this == this.orderRenders[0]){
                this.orderRenders.splice(0, 1); //删除自己
            }

            if(this.orderRenders.length > 1){
                this.orderRenders.sort((ln, rn)=>{
    
                    if(!ln._realRenderFunc){
                        ln._realRenderFunc = ln._render;
                        ln._render = emptyRender;
                    }
                    
                    if(!rn._realRenderFunc){
                        rn._realRenderFunc = rn._render;
                        rn._render = emptyRender;
                    }
    
                    return ln.node.____order - rn.node.____order;
                });
            }else{
                for (const r of this.orderRenders) {
                    if(!r._realRenderFunc){
                        r._realRenderFunc = r._render;
                        r._render = emptyRender;
                    }
                }
            }
        }
    }

    postUpdateAssembler (batcher: any) {
        if(IS_OPEN_BATCH && !this.isClearSlef){
            if(this._renderFlag && this.orderRenders){
                for (const dr of this.orderRenders) {
                    if(dr.node && dr.node.activeInHierarchy && dr._renderFlag && dr._realRenderFunc){
                        dr._realRenderFunc(batcher);
                    }
                }
            }
        }else{
            super.postUpdateAssembler(batcher);
        }
    }
}